package com.gitee.kamismile.disruptorEx.commandhandling.callbacks;

import com.gitee.kamismile.disruptorEx.commandhandling.CommandCallback;
import com.gitee.kamismile.disruptorEx.commandhandling.CommandMessage;
import com.gitee.kamismile.stone.commmon.exception.BusinessException;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import static java.util.Objects.requireNonNull;

public class FutureCallback<R> extends CompletableFuture<R> implements CommandCallback<R> {

    @Override
    public void onSuccess(CommandMessage commandMessage, R executionResult) {
        super.complete(executionResult);
    }

    @Override
    public void onFailure(CommandMessage commandMessage, Throwable cause) {
        super.completeExceptionally(requireNonNull(cause));
    }

    public R getResult() {
        try {
            return get();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return null;
        } catch (ExecutionException e) {
            throw asRuntime(e);
        }
    }


    public R getResult(long timeout, TimeUnit unit) {
        try {
            return get(timeout, unit);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return null;
        } catch (TimeoutException e) {
            return null;
        } catch (ExecutionException e) {
            throw asRuntime(e);
        }
    }

    private RuntimeException asRuntime(Exception e) {
        Throwable failure = e.getCause();
        if (failure instanceof Error) {
            throw (Error) failure;
        } else if (failure instanceof RuntimeException) {
            return (RuntimeException) failure;
        } else {
            return new BusinessException(-1, failure.getMessage());
        }
    }
}
